﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using YShop.Application.Contracts.System.DataItems;
using YShop.Application.Contracts.Views;
using YShop.Core;
using YShop.Core.Managers.Caches;
using YShop.Core.System;

namespace YShop.Application.System
{
    /// <summary>
    /// 系统数据项
    /// </summary>
    [ApiDescriptionSettings("System")]
    public class SystemDataItemService : IDynamicApiController
    {
        private Dictionary<string, DataItemDto> CodeData { get; set; }
        private Dictionary<SystemDataItemAttribute, MethodInfo> CodeAction { get; set; }

        public List<DataItemDto> SystemDataItems => App.GetService<CacheManager>().GetOrCreate("SystemDataItemService.All", _ =>
        {
            Initialize().Wait();
            var list = new List<DataItemDto>(CodeData.Values.Where(c => c.Type == DataItemType.System));
            return list;
        });
        

        public SystemDataItemService()
        {
            CodeData = new Dictionary<string, DataItemDto>();
            CodeAction = new Dictionary<SystemDataItemAttribute, MethodInfo>();
            Build();
        }

        /// <summary>
        /// 构建
        /// </summary>
        private void Build()
        {
            foreach (var type in App.EffectiveTypes.Where(t => t.Namespace.StartsWith("YShop")))
            {
                // 系统枚举
                if (type.IsEnum)
                {
                    var xmlComment = Utils.GetEnumNamesComment(type);
                    var dataItem = new DataItemDto
                    {
                        Code = type.Name,
                        Name = xmlComment.ContainsKey(type.Name) ? xmlComment[type.Name] : string.Empty,
                        Type = DataItemType.System,
                    };
                    var index = 0;
                    foreach (var name in type.GetEnumNames())
                    {
                        dataItem.Details ??= new List<dynamic>();
                        dataItem.Details.Add(new DataItemDetailDto
                        {
                            DataItemId = dataItem.Id,
                            Label = xmlComment.ContainsKey(name) ? xmlComment[name] : string.Empty,
                            Value = index.ToString(),
                            ShortName = xmlComment.ContainsKey(name) ? xmlComment[name] : string.Empty,

                        });
                        index++;
                    }
                    CodeData.Add(type.Name, dataItem);
                }

                if (type.GetInterface("IBaseService") != null)
                {
                    foreach (var action in type.GetMethods())
                    {
                        var attribute = action.GetCustomAttributes(true).FirstOrDefault(a => a is SystemDataItemAttribute);
                        if (attribute != null)
                        {
                            var systemDataItemAttribute = (SystemDataItemAttribute)attribute;

                            CodeAction.Add(systemDataItemAttribute, action);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private async Task Initialize()
        {
            //foreach (var key in CodeAction.Keys)
            //{
            //    var action = CodeAction[key];

            //    CodeData[key.Code] = new DataItemDto
            //    {
            //        Code = key.Code,
            //        Type = DataItemType.Source,
            //        DetailsDataType = key.Type,
            //        Details = action
            //    };
            //}
            await Task.CompletedTask;
        }
        /// <summary>
        /// 获取单个系统字典数据
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<dynamic> GetAction(string code)
        {
            var option = CodeAction.Keys.FirstOrDefault(s => s.Code == code);
            var action = CodeAction[option];
            dynamic data;
            if (option.IsAync)
                data = await (Task<dynamic>)action.Invoke(App.GetService(action.DeclaringType), null);
            else
                data = action.Invoke(App.GetService(action.DeclaringType), null);

            if (!CodeData.ContainsKey(option.Code))
                CodeData.Add(option.Code, null);
            return data;
        }
    }

}
